﻿using BaseTool;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;

namespace Airthmetic
{
    /// <summary>
    /// 图片工具类
    /// </summary>
    public static class ImageTool
    {
        #region 进制转换
        /// <summary>
        /// 自然二进制转格雷码
        /// </summary>
        /// <param name="value"></param>
        /// <param name="offset"></param>
        /// <returns></returns>
        public static int BinaryToGray(int value, int offset) { return util_binaryToGray(value + offset); }
        /// <summary>
        /// 格雷码转自然二进制
        /// </summary>
        /// <param name="value"></param>
        /// <param name="offset"></param>
        /// <returns></returns>
        public static int GrayToBinary(int value, int offset) { return util_grayToBinary(value, 32) - offset; }

        /// <summary> 
        /// 此函数的目的是将无符号二进制数转换为反映二进制格雷码
        /// http://en.wikipedia.org/wiki/Gray_code
        /// </summary>
        public static int util_binaryToGray(int num) { return (num >> 1) ^ num; }
        /// <summary>
        /// 此函数的目的是将反射的二进制格雷码数转换为二进制数。
        /// http://en.wikipedia.org/wiki/Gray_code
        /// </summary>
        /// <param name="num"></param>
        /// <param name="numBits"></param>
        /// <returns></returns>
        public static int util_grayToBinary(int num, int numBits)
        {
            for (int shift = 1; shift < numBits; shift <<= 1)
            {
                num ^= num >> shift;
            }
            return num;
        }


        /// <summary>
        /// 是否无效值
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool INVALID(float value) { return value == float.NaN; }
        /// <summary>
        /// 是否无效值
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool INVALID(Vec2f value) { return value[0] == float.NaN || value[1] == float.NaN; }
        /// <summary>
        /// 是否无效值
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool INVALID(Vec3f value) { return value[0] == float.NaN || value[1] == float.NaN || value[2] == float.NaN; }
        #endregion

        #region bayer图像提取单个颜色值
        /// <summary>
        /// bayer BG8 提取四通道像素值
        /// </summary>
        /// <param name="BG8"></param>
        /// <param name="Blue"></param>
        /// <param name="Green1"></param>
        /// <param name="Green2"></param>
        /// <param name="Red"></param>
        /// <returns></returns>
        public static bool BayerBG8ToBGGR(Mat BG8, out Mat Blue, out Mat Green1, out Mat Green2, out Mat Red)
        {
            try
            {
                Blue = new Mat(BG8.Height / 2, BG8.Width / 2, MatType.CV_8UC1);
                Green1 = new Mat(BG8.Height / 2, BG8.Width / 2, MatType.CV_8UC1);
                Green2 = new Mat(BG8.Height / 2, BG8.Width / 2, MatType.CV_8UC1);
                Red = new Mat(BG8.Height / 2, BG8.Width / 2, MatType.CV_8UC1);

                for (int row = 0; row < Blue.Height; row++)
                {
                    for (int col = 0; col < Blue.Width; col++)
                    {
                        Blue.Set<short>(row, col, BG8.At<short>(row * 2, col * 2));
                        Green1.Set<short>(row, col, BG8.At<short>(row * 2, col * 2 + 1));
                        Green2.Set<short>(row, col, BG8.At<short>(row * 2 + 1, col * 2));
                        Red.Set<short>(row, col, BG8.At<short>(row * 2 + 1, col * 2 + 1));
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                Log.SaveError(ex);
                Blue = null;
                Green1 = null;
                Green2 = null;
                Red = null;
                return false;
            }
        }

        /// <summary>
        /// bayer GB8 提取四通道像素值
        /// </summary>
        /// <param name="GB8"></param>
        /// <param name="Green1"></param>
        /// <param name="Blue"></param>
        /// <param name="Red"></param>
        /// <param name="Green2"></param>
        /// <returns></returns>
        public static bool BayerGB8ToGBRG(Mat GB8, out Mat Green1, out Mat Blue, out Mat Red, out Mat Green2)
        {
            try
            {
                Green1 = new Mat(GB8.Height / 2, GB8.Width / 2, MatType.CV_8UC1);
                Blue = new Mat(GB8.Height / 2, GB8.Width / 2, MatType.CV_8UC1);
                Red = new Mat(GB8.Height / 2, GB8.Width / 2, MatType.CV_8UC1);
                Green2 = new Mat(GB8.Height / 2, GB8.Width / 2, MatType.CV_8UC1);

                for (int row = 0; row < Blue.Height; row++)
                {
                    for (int col = 0; col < Blue.Width; col++)
                    {
                        Green1.Set<short>(row, col, GB8.At<short>(row * 2, col * 2));
                        Blue.Set<short>(row, col, GB8.At<short>(row * 2, col * 2 + 1));
                        Red.Set<short>(row, col, GB8.At<short>(row * 2 + 1, col * 2));
                        Green2.Set<short>(row, col, GB8.At<short>(row * 2 + 1, col * 2 + 1));
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                Log.SaveError(ex);
                Green1 = null;
                Blue = null;
                Red = null;
                Green2 = null;
                return false;
            }
        }

        /// <summary>
        /// bayer RG8 提取四通道像素值
        /// </summary>
        /// <param name="RG8"></param>
        /// <param name="Red"></param>
        /// <param name="Green1"></param>
        /// <param name="Green2"></param>
        /// <param name="Blue"></param>
        /// <returns></returns>
        public static bool BayerRG8ToRGGB(Mat RG8, out Mat Red, out Mat Green1, out Mat Green2, out Mat Blue)
        {
            try
            {
                Red = new Mat(RG8.Height / 2, RG8.Width / 2, MatType.CV_8UC1);
                Green1 = new Mat(RG8.Height / 2, RG8.Width / 2, MatType.CV_8UC1);
                Green2 = new Mat(RG8.Height / 2, RG8.Width / 2, MatType.CV_8UC1);
                Blue = new Mat(RG8.Height / 2, RG8.Width / 2, MatType.CV_8UC1);

                for (int row = 0; row < Blue.Height; row++)
                {
                    for (int col = 0; col < Blue.Width; col++)
                    {
                        Red.Set<short>(row, col, RG8.At<short>(row * 2, col * 2));
                        Green1.Set<short>(row, col, RG8.At<short>(row * 2, col * 2 + 1));
                        Green2.Set<short>(row, col, RG8.At<short>(row * 2 + 1, col * 2));
                        Blue.Set<short>(row, col, RG8.At<short>(row * 2 + 1, col * 2 + 1));
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                Log.SaveError(ex);
                Red = null;
                Green1 = null;
                Green2 = null;
                Blue = null;
                return false;
            }
        }

        /// <summary>
        /// bayer GR8 提取四通道像素值
        /// </summary>
        /// <param name="GB8"></param>
        /// <param name="Green1"></param>
        /// <param name="Red"></param>
        /// <param name="Blue"></param>
        /// <param name="Green2"></param>
        /// <returns></returns>
        public static bool BayerGR8ToGRBG(Mat GB8, out Mat Green1, out Mat Red, out Mat Blue, out Mat Green2)
        {
            try
            {
                Green1 = new Mat(GB8.Height / 2, GB8.Width / 2, MatType.CV_8UC1);
                Red = new Mat(GB8.Height / 2, GB8.Width / 2, MatType.CV_8UC1);
                Blue = new Mat(GB8.Height / 2, GB8.Width / 2, MatType.CV_8UC1);
                Green2 = new Mat(GB8.Height / 2, GB8.Width / 2, MatType.CV_8UC1);

                for (int row = 0; row < Blue.Height; row++)
                {
                    for (int col = 0; col < Blue.Width; col++)
                    {
                        Green1.Set<short>(row, col, GB8.At<short>(row * 2, col * 2));
                        Red.Set<short>(row, col, GB8.At<short>(row * 2, col * 2 + 1));
                        Blue.Set<short>(row, col, GB8.At<short>(row * 2 + 1, col * 2));
                        Green2.Set<short>(row, col, GB8.At<short>(row * 2 + 1, col * 2 + 1));
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                Log.SaveError(ex);
                Green1 = null;
                Red = null;
                Blue = null;
                Green2 = null;
                return false;
            }
        }
        #endregion

        #region Mat转换
        /// <summary>
        /// 获取完整图像
        /// </summary>
        /// <param name="inputImage"> 传入图像 </param>
        /// <param name="width"> 宽 </param>
        /// <param name="height"> 高 </param>
        /// <returns></returns>
        public static Mat GetFullImage(Mat inputImage, int width, int height)
        {
            try
            {
                if (inputImage == null)
                    throw new ArgumentNullException("Mat");

                if (inputImage.Width == 1)
                {
                    byte[] data;
                    inputImage.GetArray(out data);
                    byte[] datas = new byte[height * width];
                    for (int r = 0; r < height; r++)
                    {
                        byte[] temp = Enumerable.Repeat(data[r], width).ToArray();
                        temp.CopyTo(datas, r * width);
                    }
                    Mat full = new Mat(height, width, MatType.CV_8UC1);
                    full.SetArray(datas);
                    return full;
                }
                else if (inputImage.Height == 1)
                {
                    byte[] data;
                    inputImage.GetArray(out data);
                    byte[] datas = new byte[height * width];
                    for (int r = 0; r < height; r++)
                    {
                        data.CopyTo(datas, r * width);
                    }
                    Mat full = new Mat(height, width, MatType.CV_8UC1);
                    full.SetArray(datas);
                    return full;
                }
                else
                {
                    throw new Exception("The inputImage image is abnormal and is not a single-row or single-column image.");
                }
            }
            catch (Exception ex)
            {
                Log.SaveError(ex);
                throw ex;
            }
        }
        /// <summary>
        /// 获取完整图像
        /// </summary>
        /// <param name="imageData"> 传入图像数据 </param>
        /// <param name="width"> 宽 </param>
        /// <param name="height"> 高 </param>
        /// <returns></returns>
        public static Mat GetFullImage(byte[] imageData, int width, int height)
        {
            try
            {
                if (imageData == null || imageData.Length == 0)
                    throw new ArgumentNullException("Mat");

                if (imageData.Length == height)
                {
                    byte[] datas = new byte[height * width];
                    for (int r = 0; r < height; r++)
                    {
                        byte[] temp = Enumerable.Repeat(imageData[r], width).ToArray();
                        temp.CopyTo(datas, r * width);
                    }
                    Mat full = new Mat(height, width, MatType.CV_8UC1);
                    full.SetArray(datas);
                    return full;
                }
                else if (imageData.Length == width)
                {
                    byte[] datas = new byte[height * width];
                    for (int r = 0; r < height; r++)
                    {
                        imageData.CopyTo(datas, r * width);
                    }
                    Mat full = new Mat(height, width, MatType.CV_8UC1);
                    full.SetArray(datas);
                    return full;
                }
                else
                {
                    throw new Exception("The length of the image data does not match the input parameters.");
                }
            }
            catch (Exception ex)
            {
                Log.SaveError(ex);
                throw ex;
            }
        }
        /// <summary>
        /// 获取Bitmap图像
        /// </summary>
        /// <param name="mat"></param>
        /// <returns></returns>
        [Obsolete("引用OpenCvSharp.Extensions，调用ToBitmap()")]
        public static Image MatToImage(Mat mat)
        {
            return BitmapConverter.ToBitmap(mat);
        }


        /// <summary>
        /// 获取Mat数据
        /// </summary>
        /// <param name="Rows"></param>
        /// <param name="Cols"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static Mat GetMat(int Rows, int Cols, double[] data)
        {
            Mat mat = new Mat(Rows, Cols, MatType.CV_64FC1);
            for (int h = 0; h < Rows; h++)
            {
                for (int w = 0; w < Cols; w++)
                {
                    mat.Set<double>(h, w, data[h * Cols + w]);
                }
            }
            return mat;
        }
        /// <summary>
        /// 获取mat数据
        /// </summary>
        /// <param name="Rows"></param>
        /// <param name="Cols"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static Mat GetMat(int Rows, int Cols, double[][] data)
        {
            Mat mat = new Mat(Rows, Cols, MatType.CV_64FC1);
            for (int h = 0; h < Rows; h++)
            {
                for (int w = 0; w < Cols; w++)
                {
                    mat.Set<double>(h, w, data[h][w]);
                }
            }
            return mat;
        }
        /// <summary>
        /// 获取mat数据
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static Mat GetMat(double[] data)
        {
            Mat mat = new Mat(1, data.Length, MatType.CV_64FC1);
            for (int w = 0; w < data.Length; w++)
            {
                mat.Set<double>(0, w, data[w]);
            }
            return mat;
        }
        /// <summary>
        /// 获取mat数据
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static Mat GetMat(double[,] data)
        {
            Mat mat = new Mat(data.GetLength(0), data.GetLength(1), MatType.CV_64FC1);
            for (int h = 0; h < data.GetLength(0); h++)
            {
                for (int w = 0; w < data.GetLength(1); w++)
                {
                    mat.Set<double>(h, w, data[h, w]);
                }
            }
            return mat;
        }

        /// <summary>
        /// 在64FC1类型下进行mat数据复制
        /// </summary>
        /// <param name="inputMat"></param>
        /// <param name="outputMat"></param>
        /// <param name="RowStart"></param>
        /// <param name="RowEnd"></param>
        /// <param name="ColStart"></param>
        /// <param name="ColEnd"></param>
        /// <exception cref="Exception"></exception>
        public static void CopyMatDouble(Mat inputMat, Mat outputMat,
            int RowStart = -1, int RowEnd = -1, int ColStart = -1, int ColEnd = -1)
        {
            if (inputMat.Type() != MatType.CV_64FC1 || outputMat.Type() != MatType.CV_64FC1)
                throw new Exception("Mat data is not of the right type");

            int rs = RowStart == -1 ? 0 : RowStart;
            int re = RowEnd == -1 ? inputMat.Rows - 1 : RowEnd;
            int cs = ColStart == -1 ? 0 : ColStart;
            int ce = ColEnd == -1 ? inputMat.Cols - 1 : ColEnd;

            for (int h = rs; h <= re; h++)
            {
                for (int w = cs; w <= ce; w++)
                {
                    outputMat.Set(h, w, inputMat.Get<double>(h, w));
                }
            }
        }

        /// <summary>
        /// 获取双精度浮点数组
        /// </summary>
        /// <param name="mat"></param>
        /// <returns></returns>
        public static double[] GetDouble(Mat mat)
        {
            List<double> OutDouble = new List<double>();

            for (int h = 0; h < mat.Rows; h++)
            {
                for (int w = 0; w < mat.Cols; w++)
                {
                    OutDouble.Add(mat.At<double>(h, w));
                }
            }
            return OutDouble.ToArray();
        }
        /// <summary>
        /// 获取双精度浮点数组
        /// </summary>
        /// <param name="mat"></param>
        /// <returns></returns>
        public static double[][] GetDouble2D(Mat mat)
        {
            double[][] OutDouble = new double[mat.Rows][];

            for (int h = 0; h < mat.Rows; h++)
            {
                List<double> d = new List<double>();
                for (int w = 0; w < mat.Cols; w++)
                {
                    d.Add(mat.At<double>(h, w));
                }
                OutDouble[h] = d.ToArray();
            }
            return OutDouble;
        }
        /// <summary>
        /// 获取双精度浮点数组
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static double[][] GetDouble2D(double[,] data)
        {
            double[][] OutDouble = new double[data.GetLength(0)][];

            for (int h = 0; h < data.GetLength(0); h++)
            {
                List<double> d = new List<double>();
                for (int w = 0; w < data.GetLength(1); w++)
                {
                    d.Add(data[h, w]);
                }
                OutDouble[h] = d.ToArray();
            }

            return OutDouble;
        }
        #endregion

        #region 图像加载
        /// <summary>
        /// 读取采集的文件夹路径列表
        /// </summary>
        /// <param name="CaliPath"></param>
        /// <param name="RecoPath"></param>
        /// <param name="Count"></param>
        public static void LoadImage(out List<string> CaliPath, out List<string> RecoPath, int Count = -1)
        {
            CaliPath = new List<string>();
            RecoPath = new List<string>();
            try
            {
                //图像采集路径 Debug\Data\Capture\
                string ReadPath = PathTool.DataCapturePath;
                if (!Directory.Exists(ReadPath))
                    return;

                string[] DateTimeDirs = Directory.GetDirectories(ReadPath);
                foreach (string DateTimeDir in DateTimeDirs)
                {
                    DirectoryInfo di = new DirectoryInfo(DateTimeDir);
                    if (Count != -1 && di.GetFiles().Count() < Count)
                        continue;

                    if (di.Name.Contains("Calibration"))
                        CaliPath.Add(DateTimeDir);
                    if (di.Name.Contains("Reconstruct"))
                        RecoPath.Add(DateTimeDir);
                }
            }
            catch (Exception ex)
            {
                Log.SaveError(ex);
            }
        }

        /// <summary>
        /// 保存mat图像
        /// </summary>
        /// <param name="dirPath"></param>
        /// <param name="fileName"></param>
        /// <param name="inputMat"></param>
        /// <param name="isTiff"></param>
        public static void SaveMat(string dirPath, string fileName, Mat inputMat, bool isTiff = false)
        {
            if (!Directory.Exists(dirPath))
                Directory.CreateDirectory(dirPath);


            MatType matType = inputMat.Type();
            if (matType == MatType.CV_8UC1)
            {
                if (isTiff)
                    Cv2.ImWrite($"{dirPath}{fileName}_Tiff_8UC1.tiff", inputMat);
                else
                    Cv2.ImWrite($"{dirPath}{fileName}_8U_C1.bmp", inputMat);
            }
            else if (matType == MatType.CV_8UC3)
            {
                if (isTiff)
                    Cv2.ImWrite($"{dirPath}{fileName}_Tiff_8UC3.tiff", inputMat);
                else
                    Cv2.ImWrite($"{dirPath}{fileName}_8U_C3.bmp", inputMat);
            }
            else if (matType == MatType.CV_8UC2)
            {
                if (isTiff)
                {
                    Cv2.ImWrite($"{dirPath}{fileName}_Tiff_8UC1.tiff", inputMat.ExtractChannel(0));
                    Cv2.ImWrite($"{dirPath}{fileName}_Tiff_8UC2.tiff", inputMat.ExtractChannel(1));
                }
                else
                {
                    Cv2.ImWrite($"{dirPath}{fileName}_8U_C1.bmp", inputMat.ExtractChannel(0));
                    Cv2.ImWrite($"{dirPath}{fileName}_8U_C2.bmp", inputMat.ExtractChannel(1));
                }
            }
            else if (matType == MatType.CV_32FC1)
            {
                if (isTiff)
                {
                    Cv2.ImWrite($"{dirPath}{fileName}_Tiff_32FC1.tiff", inputMat);
                }
                else
                {
                    Mat mat2 = new Mat(inputMat.Rows, inputMat.Cols, MatType.CV_8UC1);
                    inputMat.ConvertTo(mat2, MatType.CV_8UC1, 1 / 255.0);
                    Cv2.ImWrite($"{dirPath}{fileName}_32FTo8U_C1.bmp", mat2);
                }
            }
            else if (matType == MatType.CV_32FC2)
            {
                if (isTiff)
                {
                    Cv2.ImWrite($"{dirPath}{fileName}_Tiff_32FC1.tiff", inputMat.ExtractChannel(0));
                    Cv2.ImWrite($"{dirPath}{fileName}_Tiff_32FC2.tiff", inputMat.ExtractChannel(1));
                }
                else
                {
                    Mat mat2 = new Mat(inputMat.Rows, inputMat.Cols, MatType.CV_8UC2);
                    inputMat.ConvertTo(mat2, MatType.CV_8UC3, 1 / 255.0);
                    Cv2.ImWrite($"{dirPath}{fileName}_32FTo8U_C1.bmp", mat2.ExtractChannel(0));
                    Cv2.ImWrite($"{dirPath}{fileName}_32FTo8U_C2.bmp", mat2.ExtractChannel(1));
                }
            }
            else if (matType == MatType.CV_32FC3)
            {
                if (isTiff)
                {
                    Cv2.ImWrite($"{dirPath}{fileName}_Tiff_32FC3.tiff", inputMat);
                }
                else
                {
                    Mat mat2 = new Mat(inputMat.Rows, inputMat.Cols, MatType.CV_8UC3);
                    inputMat.ConvertTo(mat2, MatType.CV_8UC3, 1 / 255.0);
                    Cv2.ImWrite($"{dirPath}{fileName}_32FTo8U_C1.bmp", mat2.ExtractChannel(0));
                    Cv2.ImWrite($"{dirPath}{fileName}_32FTo8U_C2.bmp", mat2.ExtractChannel(1));
                    Cv2.ImWrite($"{dirPath}{fileName}_32FTo8U_C3.bmp", mat2.ExtractChannel(2));
                }
            }

        }

        /// <summary>
        /// 读取标定的文件夹路径和参数
        /// </summary>
        /// <param name="CaliPath"></param>
        /// <param name="CaliName"></param>
        /// <param name="CaliResult"></param>
        public static void LoadCalibration(out List<string> CaliPath, out List<string> CaliName, out List<CalibrationResult> CaliResult)
        {
            CaliPath = new List<string>();
            CaliName = new List<string>();
            CaliResult = new List<CalibrationResult>();

            try
            {
                //标定路径 Debug\Data\Calibration\
                string ReadPath = PathTool.DataCalibrationPath;
                if (!Directory.Exists(ReadPath))
                    return;

                string[] DateTimeDirs = Directory.GetDirectories(ReadPath);
                foreach (string DateTimeDir in DateTimeDirs)
                {
                    DirectoryInfo di = new DirectoryInfo(DateTimeDir + "\\Xml");
                    if (!di.Exists)
                        continue;

                    //string tickIni;
                    //string IniPath = di.FullName + "\\Index.ini";
                    //if (!File.Exists(IniPath))
                    //    continue;
                    //FileTool.ReadIni(IniPath, "Calibration", "CalibrationTicks", out tickIni);
                    //DateTime CalibrationTime = new DateTime(long.Parse(tickIni));

                    string XmlPath = di.FullName + "\\CalibrationResult.xml";
                    if (!File.Exists(XmlPath))
                        continue;
                    CalibrationResult cr = (CalibrationResult)FileTool.ReadXML(XmlPath, typeof(CalibrationResult));

                    CaliPath.Add(DateTimeDir);
                    CaliName.Add(DateTimeDir.Split('\\').Last());
                    CaliResult.Add(cr);
                    //if (di.Name.Contains(MyGlobal.Calibration))
                    //    CaliPath.Add(DateTimeDir);
                    //if (di.Name.Contains(MyGlobal.Reconstruct))
                    //    RecoPath.Add(DateTimeDir);
                }
            }
            catch (Exception ex)
            {
                Log.SaveError(ex);
            }
        }
        /// <summary>
        /// 读取点云数据
        /// </summary>
        /// <param name="PlyPath">点云路径</param>
        /// <param name="ImagePath">显示图像路径</param>
        /// <param name="ReName">名称</param>
        public static void LoadReconstruct(out List<string> PlyPath, out List<string> ImagePath, out List<string> ReName)
        {
            PlyPath = new List<string>();
            ImagePath = new List<string>();
            ReName = new List<string>();

            try
            {
                //标定路径 Debug\Data\Reconstruct\
                string ReadPath = PathTool.DataReconstructPath;
                if (!Directory.Exists(ReadPath))
                    return;

                string[] DateTimeDirs = Directory.GetDirectories(ReadPath);
                foreach (string DateTimeDir in DateTimeDirs)
                {
                    DirectoryInfo di = new DirectoryInfo(DateTimeDir + "\\ReconstructImage");
                    if (!di.Exists)
                        continue;

                    FileInfo[] fis = di.GetFiles();
                    foreach (FileInfo fi in fis)
                    {
                        if (!fi.Name.Contains("PointCloud_6.ply"))
                            continue;

                        string ticks = fi.Name.Replace("_PointCloud_6.ply", "");
                        DateTime dt = new DateTime(long.Parse(ticks));

                        FileInfo ImageFile = new FileInfo($"{di}\\{ticks}\\2_ColorImage_8U_C3.bmp");

                        PlyPath.Add(fi.FullName);
                        ImagePath.Add(ImageFile.Exists ? ImageFile.FullName : null);
                        ReName.Add($"{di.Parent.Name} （{ticks}）");
                    }
                }
            }
            catch (Exception ex)
            {
                Log.SaveError(ex);
            }
        }
        #endregion
    }
}